package com.Chat;
import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.*;
import java.util.concurrent.*;

// 服务器主类
public class MultiThreadedChatServer {
    private static final int PORT = 8080;// 服务器端口

    /*客户端处理程序列表，key为客户端ID也就是名称，value为处理程序，通过value可以调用该进程的方法*/
    private static ConcurrentHashMap<String, ClientHandler> clients = new ConcurrentHashMap<>();//存放在集合中不会重复
    private static int clientIdCounter = 1;//生成客户端ID的计数器，简单模拟，以后通过数据库实现登陆注册和用户账号存储功能
    //存储用户的客户端ID和用户名
    public static ConcurrentHashMap<String, String> onlineUsers = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        System.out.println("聊天服务器启动，端口: " + PORT);// 输出服务器启动信息

        try {
            ServerSocket serverSocket = new ServerSocket(PORT);//开始监听端口
            while (true) {
                Socket clientSocket = serverSocket.accept();// 接受新的客户端连接
                String clientId = "Client-" + clientIdCounter++;//用字符串拼接的方法生成客户端ID
                /*getHostAddress()：返回IP地址的字符串表示形式（不包含主机名）；getInetAddress()返回一个 InetAddress 对象，表示IP地址*/
                System.out.println("新客户端连接: " + clientId + " - " + clientSocket.getInetAddress().getHostAddress());

                ClientHandler clientHandler = new ClientHandler(clientSocket, clientId);// 创建客户端处理程序
                clients.put(clientId, clientHandler);//将客户端ID作为键，将客户端处理程序作为值保存在clients集合中

                Thread clientThread = new Thread(clientHandler);//创建线程
                clientThread.start();//启动线程
            }
        } catch (IOException e) {
            System.err.println("服务器错误: " + e.getMessage());
        }
    }

    // 向特定客户端发送消息
    public static void sendMessageToClient(String targetClientId, String message, String senderId) {
        ClientHandler targetClient = clients.get(targetClientId);// 按照客户端ID获取目标客户端的处理进程可以来通过里面的方法来发送消息
        if (targetClient != null) {// 如果目标客户端存在,则发送消息给该客户端
            String senderName = onlineUsers.get(senderId);
            if (senderName != null) {
                targetClient.sendMessage("来自 " + senderName + ": " + message);
            } else {
                targetClient.sendMessage("来自 " + senderId + ": " + message);
            }
        }
    }

    // 广播在线客户端列表
    public static void broadcastClientList() {
        if (onlineUsers.isEmpty()) {
            return;
        }

        StringBuilder clientList = new StringBuilder("在线用户: ");// 创建客户端列表字符串
        for (String username : onlineUsers.values()) {//遍历在线用户名
            clientList.append(username).append(" ");// 添加用户名
        }

        // 广播客户端列表给所有在线客户端
        for(String clientId : onlineUsers.keySet()){
            ClientHandler client = clients.get(clientId);
            if (client != null) {
                client.sendMessage("系统提示: " + clientList.toString());
            }
        }
    }

    // 移除客户端
    public static void removeClient(String clientId) {
        String username = onlineUsers.get(clientId);
        clients.remove(clientId);
        onlineUsers.remove(clientId);
        System.out.println("用户断开连接: " + (username != null ? username : clientId));
        broadcastClientList();// 广播在线客户端列表
    }

    // 添加用户到在线列表
    public static void addOnlineUser(String clientId, String username) {
        onlineUsers.put(clientId, username);
        broadcastClientList();
    }

    //注册用户
    public static int registerUser(String username, String password) {
        // 从配置文件中读取数据库连接信息
        ResourceBundle resourceBundle = ResourceBundle.getBundle("jdbc");
        String driver = resourceBundle.getString("driver");
        String url = resourceBundle.getString("url");
        String dbUser = resourceBundle.getString("user");        // 数据库用户名
        String dbPassword = resourceBundle.getString("password"); // 数据库密码

        Connection connection = null;
        PreparedStatement checkStmt = null;
        PreparedStatement insertStmt = null;
        ResultSet rs = null;

        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, dbUser, dbPassword);

            // 先检查用户名是否已存在
            String checkSql = "SELECT username FROM user WHERE username = ?";
            checkStmt = connection.prepareStatement(checkSql);
            checkStmt.setString(1, username);
            rs = checkStmt.executeQuery();

            if (rs.next()) {
                return 2; // 用户已存在
            }

            // 插入新用户
            String insertSql = "INSERT INTO user (username, password) VALUES (?, ?)";
            insertStmt = connection.prepareStatement(insertSql);
            insertStmt.setString(1, username);
            insertStmt.setString(2, password);

            int rowsAffected = insertStmt.executeUpdate();
            if (rowsAffected > 0) {
                return 1; // 注册成功
            } else {
                return 3; // 插入失败
            }

        } catch (Exception e) {
            e.printStackTrace();
            return 3; // 数据库错误
        } finally {
            // 关闭资源
            try {
                if (rs != null) rs.close();
                if (checkStmt != null) checkStmt.close();
                if (insertStmt != null) insertStmt.close();
                if (connection != null) connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    // 登录用户
    public static int loginUser(String username, String password, String clientId) {
        // 从配置文件中读取数据库连接信息
        ResourceBundle resourceBundle = ResourceBundle.getBundle("jdbc");
        String driver = resourceBundle.getString("driver");
        String url = resourceBundle.getString("url");
        String dbUser = resourceBundle.getString("user");        // 数据库用户名
        String dbPassword = resourceBundle.getString("password"); // 数据库密码

        Connection connection = null;
        PreparedStatement pstmt = null;
        PreparedStatement checkStmt = null;
        ResultSet rs = null;
        ResultSet checkRs = null;

        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, dbUser, dbPassword);

            // 检查用户名和密码
            String sql = "SELECT username FROM user WHERE username = ? AND password = ?";
            pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, username);
            pstmt.setString(2, password);
            rs = pstmt.executeQuery();

            if (rs.next()) {
                // 登录成功，添加到在线用户列表
                addOnlineUser(clientId, username);
                return 0; // 登录成功
            } else {
                // 检查用户名是否存在
                String checkUserSql = "SELECT username FROM user WHERE username = ?";
                checkStmt = connection.prepareStatement(checkUserSql);
                checkStmt.setString(1, username);
                checkRs = checkStmt.executeQuery();

                if (checkRs.next()) {
                    return 2; // 密码错误
                } else {
                    return 1; // 用户不存在
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 3; // 系统错误
        } finally {
            // 关闭资源
            try {
                if (rs != null) rs.close();
                if (checkRs != null) checkRs.close();
                if (pstmt != null) pstmt.close();
                if (checkStmt != null) checkStmt.close();
                if (connection != null) connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    // 获取所有客户端ID
    public static Set<String> getClientIds() {
        return clients.keySet();
    }

    // 获取所有在线用户名
    public static Set<String> getOnlineUsernames() {
        return new HashSet<>(onlineUsers.values());
    }

    // 根据用户名获取客户端ID
    public static String getClientIdByUsername(String username) {
        for (Map.Entry<String, String> entry : onlineUsers.entrySet()) {
            if (entry.getValue().equals(username)) {
                return entry.getKey();
            }
        }
        return null;
    }

    // 检查用户是否在线
    public static boolean isUserOnline(String username) {
        return onlineUsers.containsValue(username);
    }

    // 广播消息给所有在线用户
    public static void broadcastMessage(String message, String senderId) {
        String senderName = onlineUsers.get(senderId);
        String formattedMessage = senderName != null ?
                "广播来自 " + senderName + ": " + message :
                "广播来自 " + senderId + ": " + message;

        for (String clientId : onlineUsers.keySet()) {
            ClientHandler client = clients.get(clientId);
            if (client != null && !clientId.equals(senderId)) {
                client.sendMessage(formattedMessage);
            }
        }
    }
}